package com.ziiwee.reduce.rest;

import com.ziiwee.reduce.rest.auto.*;
import com.ziiwee.reduce.rest.utils.SpringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpMethod;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerResponse;

import java.util.Collection;
import java.util.List;

/**
 * @author ziiwee
 * @date 2020/8/18
 */
@Configuration
@Import(SpringUtil.class)
public class RestConfiguration {

    @Bean
    public RouterFunction<ServerResponse> restAutoHandleProviderRoute(ResourceMapping mapping, RestAutoHandleProvider provider) {
        Collection<ResourceInfo> all = mapping.getAll();
        if (all.size() <= 0) {
            return null;
        }
        RouterFunctions.Builder route = RouterFunctions.route();
        for (ResourceInfo info : mapping.getAll()) {
            route.GET(String.format("/%s", info.getName()), request -> provider.render(HttpMethod.GET, info, request));
            route.GET(String.format("/%s/{id}", info.getName()), request -> provider.render(HttpMethod.GET, info, request));
            route.POST(String.format("/%s", info.getName()), request -> provider.render(HttpMethod.POST, info, request));
            route.PUT(String.format("/%s/{id}", info.getName()), request -> provider.render(HttpMethod.PUT, info, request));
            route.PATCH(String.format("/%s/{id}", info.getName()), request -> provider.render(HttpMethod.PATCH, info, request));
            route.DELETE(String.format("/%s/{id}", info.getName()), request -> provider.render(HttpMethod.DELETE, info, request));
        }
        return route.build();
    }

    @Bean
    @ConditionalOnMissingBean(ResourceMapping.class)
    @Autowired(required = false)
    public ResourceMapping resourceMapping(List<ResourceService<?, ?>> services) {
        DefaultResourceMapping mapping = new DefaultResourceMapping();
        if (services != null) {
            services.forEach(mapping::register);
        }
        return mapping;
    }

    @Bean
    @ConditionalOnMissingBean(RestAutoHandleProvider.class)
    @Autowired(required = false)
    public RestAutoHandleProvider restAutoHandleProvider(SpringDataWebProperties springDataWebProperties) {
        if (springDataWebProperties != null) {
            return new DefaultRestAutoHandlerProvider(springDataWebProperties);
        }
        return new DefaultRestAutoHandlerProvider();
    }

}
